home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / qualitas / dpmilib.txt < prev    next >
Text File  |  1994-04-22  |  30KB  |  749 lines

  1.  
  2.  (C) Copyright 1992, Qualitas, Inc. All Rights Reserved
  3.  
  4.  Qualitas C/C++ Libraries for DPMI
  5.  
  6.  ** Contents of this file **
  7.  
  8.  1. Introduction
  9.  2. Requirements
  10.  3. Limitations
  11.  4. Building the Example Programs
  12.  5. Building the DPMI libraries
  13.  6. Using the C library
  14.  7. Using the C++ class library
  15.  
  16.  **********************************************************************
  17.  
  18.  1. Introduction
  19.  
  20.  The Qualitas C/C++ Libraries for DPMI provide the C/C++ programmer with
  21.  easy access to DPMI.  The purpose of the libraries is to allow developers
  22.  to gain familiarity with DPMI concepts, to aid in understanding of how
  23.  DPMI can be used, and to serve as a platform for experimentation with
  24.  DPMI hosts via the creation of small model C/C++ applications.
  25.  
  26.  The directories are structured as follows:
  27.  
  28.                      top
  29.                       |
  30.       +------------------+--------+---------+------------------+
  31.       |             |            |           |
  32.      BC2            BC3            MSC6         MSC7
  33.       |             |            |           |
  34.   +-------+------+   +-------+------+    +-------+------+   +-------+------+
  35.   |    |    |     |   |      |    |    |    |    |      |    |   |    |    |      |
  36.  LIB   |    |     |  LIB   |    |    |  LIB   |      |    |  LIB    |    |      |
  37.     LIBSRC  |     |     LIBSRC  |    |      LIBSRC  |    |     LIBSRC  |      |
  38.      INCLUDE |        INCLUDE |           INCLUDE |      INCLUDE |
  39.           EXAMPLES         EXAMPLES        EXAMPLES          EXAMPLES
  40.  
  41.  For convenience of installation, the distribution provides a copy of the
  42.  source code for the libraries and examples in each compiler directory.
  43.  The primary differences between compiler directories are (1) the makefiles
  44.  differ, and (2) some of the source code distributed with the compilers
  45.  has been modified for operation in conjunction with the DPMI libraries,
  46.  and those modules are included in their respective directories.
  47.  
  48.     \        this README file
  49.     .\MSC7LIB    Microsoft C/C++ 7.0 support
  50.     .\MSC6LIB    Microsoft C 6.0 support
  51.     .\BC3LIB    Borland C/C++ 3.0 support
  52.     .\BC2LIB    Borland C/C++ 2.0 support
  53.     .\xxx\LIBSRC    Source code for the DPMI libraries
  54.     .\xxx\INCLUDE    Header files required for source and examples
  55.     .\xxx\EXAMPLES    Source code for the example programs
  56.  
  57. We have include a batch file to simplify installation.
  58.  
  59. Use the following syntax to install the Qualitas DPMI Library:
  60.  
  61. INSTALL path library [source drive]
  62.  
  63. where "path" points to the directory into which the DPMI library
  64. will be installed and "library" is the specific version of the DPMI
  65. library you wish installed.  Source drive is the floppy drive
  66. echo from which you are installing (default = A)
  67.  
  68. Select the library from the following:
  69.  
  70. BC2     Borland C++ version 2.x comaptible library
  71. BC3     Borland C++ version 3.x comaptible library
  72. MSC6     Microsoft C verson 6.x comaptible library
  73. MSC7     Microsoft C verson 7.x comaptible library
  74.  
  75. Example:  INSTALL C:\TOOLS MSC6 B
  76.  
  77. would install the Microsoft C 6 compatible DPMI library from B:
  78. to C:\TOOLS.
  79.  
  80. If you prefer to install the library manually, use the following
  81. commands. This example would install the Borland C++ version 3.0
  82. library:
  83.  
  84.     C> md DPMILIBS
  85.     C> cd DPMILIBS
  86.     C:\DPMILIBS> cd a:\BC3LIB
  87.     C:\DPMILIBS> xcopy a: /s
  88.  
  89.  **********************************************************************
  90.  
  91.  2. Requirements
  92.  
  93.  The requirements depend upon which C compiler you are using:
  94.  
  95.  Compiler    Processor    Assembler    Linker        Librarian
  96.  --------    ---------    ---------    ------        ---------
  97.  Microsoft v7    80386        MASM 6.0    LINK 5.30    LIB 3.20
  98.  Microsoft v6    80286        MASM 6.0+5.1    LINK 5.10    LIB 3.18
  99.  Borland v3    80286        TASM 3.0    TLINK 5.0    TLIB 3.02
  100.  Borland v2    80286        TASM 2.5    TLINK 4.0    TLIB 3.02
  101.  
  102.  NOTE:    The librarian and assembler are only required if you wish to
  103.     rebuild the libraries.    They are not required to build the
  104.     examples or other applications.
  105.  
  106.  Each compiler requires the small model libraries.  The Microsoft compilers
  107.  require the include files for the startup source to rebuild the DPMI
  108.  libraries.
  109.  
  110.  **********************************************************************
  111.  
  112.  3. Limitations
  113.  
  114.  * Only small model is supported.  It is possible, however, to use
  115.    far pointers that are dynamically created, for example, by using
  116.    the MK_FP macro.  Statically initialized far pointers will work
  117.    only if they refer to the default code segment or the default data
  118.    segment.
  119.  
  120.  * Floating point is not supported.  The run-time requirements create
  121.    complications which are beyond the scope of this implementation.
  122.  
  123.  * Errors may result from use of run time library functions that require
  124.    running clean-up routines at exit time, if such clean-up routines
  125.    utilize real mode far pointers created prior to entering protected mode.
  126.  
  127.  **********************************************************************
  128.  
  129.  4. Building the Example Programs
  130.  
  131.  The .\EXAMPLES directory contains the following programs:
  132.  
  133.  * HELLO.C   A simple C program that illustrates how to enter
  134.          protected mode, and how to call the DPMI C library.
  135.  * QSORT.C   A program that sorts stdin to stdout. It uses DPMI to
  136.          allocate buffers, which enables it to sort very
  137.          large files in memory.
  138.  * XMEM.CPP  A C++ program that illustrates the use of the classes in
  139.          the DPMI class libraries that are related to memory usage.
  140.  * XINTR.CPP A C++ program that illustrates the use of the classes in
  141.          the DPMI class libraries that are related to interrupt handling.
  142.  * XREAL.CPP A C++ program that illustrates the use of the classes in
  143.          the DPMI class libraries that are related to calling real
  144.          mode functions and real mode call-backs.
  145.  * XCEPT.CPP A C++ program that illustrates the use of the classes in
  146.          the DPMI class libraries that are related to exception handling.
  147.  
  148.  More detail about using the libraries and classes is found below.
  149.  
  150.  
  151.  ** To build the examples with Microsoft C 7.0
  152.  
  153.     - Your current directory must be the MSC7\EXAMPLES directory.
  154.     - CL and LINK for MS C 7.0 must be on your path.
  155.     - Your INCLUDE and LIB environment variables must be set for
  156.       a normal MS C 7.0 build.
  157.     - Issue the command NMAKE.
  158.  
  159.  ** To build the examples with Microsoft C 6.0
  160.  
  161.     NOTE: the C++ examples are not built for MS C 6.0
  162.  
  163.     - Your current directory must be the MSC6\EXAMPLES directory.
  164.     - CL and LINK for MS C 6.0 must be on your path.
  165.     - Your INCLUDE and LIB environment variables must be set for
  166.       a normal MS C 6.0 build.
  167.     - Issue the command NMAKE.
  168.  
  169.  ** To build the examples with Borland C++ 3.0
  170.  
  171.     - Your current directory must be the BC3\EXAMPLES directory.
  172.     - BCC and TLINK for BC++ 3.0 must be on your path.
  173.     - The BC3LIB variable in the MAKEFILE must be set to the
  174.       directory where your Borland C++ libraries
  175.       reside.  Edit MAKEFILE and locate the BC3LIB line.
  176.       Change the right hand side of the statement
  177.       as needed for your environment.
  178.     - Issue the command MAKE.
  179.  
  180.  ** To build the examples with Borland C++ 2.0
  181.  
  182.     - Your current directory must be the EXAMPLES directory.
  183.     - BCC and TLINK for BC++ 2.0 must be on your path.
  184.     - The BC2LIB variable in the MAKEFILE must be set to the
  185.       directory where your Borland C++ libraries
  186.       reside.  Edit MAKEFILE and locate the BC2LIB line.
  187.       Change the right hand side of the statement
  188.       as needed for your environment.
  189.     - Issue the command MAKE.
  190.  
  191.  **********************************************************************
  192.  
  193.  5. Building the DPMI libraries
  194.  
  195.  It is not necessary to rebuild the libraries in order to build the examples
  196.  or to build other applications.  However, in the event you wish to modify
  197.  the library source code, the following instructions are provided for
  198.  rebuilding the libraries:
  199.  
  200.  ** To build the libraries with Microsoft C 7.0
  201.  
  202.     - Your current directory must be the MSC7\LIBSRC directory.
  203.     - CL, MASM (v6.0) and LINK for MS C 7.0 must be on your path.
  204.     - Your INCLUDE and LIB environment variables must be set for
  205.       a normal MS C 7.0 build.
  206.     - The C7DIR variable in the makefile must
  207.       be set to the directory where your Microsoft C++ distribution
  208.       resides.  Edit MAKEFILE and locate the C7DIR= line
  209.       Change the right hand side of the statement
  210.       as needed for your environment.
  211.     - Issue the command NMAKE.
  212.  
  213.  ** To build the libraries with Microsoft C 6.0
  214.  
  215.     NOTE: the C++ libraries are not built for MS C 6.0
  216.  
  217.     - Your current directory must be the MSC6\LIBSRC directory.
  218.     - CL and LINK for MS C 6.0 must be on your path.
  219.     - Your INCLUDE and LIB environment variables must be set for
  220.       a normal MS C 6.0 build.
  221.     - The C6DIR variable in the MAKEFILE must
  222.       be set to the directory where your Microsoft C distribution
  223.       resides.  Edit MAKEFILE and locate the C6DIR= line.
  224.       Change the right hand side of the statement
  225.       as needed for your environment.
  226.     - The ASM51 variable in the MAKEFILE must be set for the
  227.       5.1 version of MASM in order to assemble the MS C 6.0 startup code.
  228.     - Issue the command NMAKE.
  229.  
  230.  
  231.  ** To build the libraries with Borland C++ 3.0
  232.  
  233.     - Your current directory must be the BC3\LIBSRC directory.
  234.     - BCC, TASM, and TLINK for BC++ 3.0 must be on your path.
  235.     - Issue the command MAKE.
  236.  
  237.  ** To build the libraries with Borland C++ 2.0
  238.  
  239.     - Your current directory must be the LIBSRC directory.
  240.     - BCC, TASM, and TLINK for BC++ 2.0 must be on your path.
  241.     - Issue the command MAKE.
  242.  
  243.  
  244.  **********************************************************************
  245.  
  246.  6. Using the C Library
  247.  
  248.  There is roughly a one-to-one mapping between the set of DPMI version 0.9
  249.  functions and the entry points of the DPMI C library.    A copy of the
  250.  DPMI specification may be a useful reference.
  251.  
  252.  A set of three higher level calls is provided for simplified memory
  253.  management. DPMImalloc(), DPMIresize(), and DPMIfree() provide a means
  254.  to allocate and address blocks of memory allocated from DPMI.    These
  255.  calls are implemented using lower level calls of the library.    Refer to
  256.  DPMIMALL.C in the LIBSRC directory to see how.
  257.  
  258.  Definitions for the C library are found in INCLUDE\DPMI.H.  This file
  259.  contains structure definitions, function prototypes, and descriptions
  260.  of each call.
  261.  
  262.  Two example programs are provided in the EXAMPLES directory. HELLO.C shows
  263.  basic usage: how to enter protected mode and call a library routine.
  264.  QSORT.C is a useful utillity for sorting large files, which is built
  265.  using the DPMImalloc family of memory management routines.
  266.  
  267.  
  268.  **********************************************************************
  269.  
  270.  7. Using the C++ Class Library
  271.  
  272.  
  273.  The class library provides a set of C++ classes that abstract several
  274.  important DPMI objects.  The header files provide descriptions and
  275.  brief examples on using the classes.
  276.  
  277.  Definitions for the DPMI classes are contained in these header files,
  278.  found in the INCLUDE directory:
  279.  
  280.     DPMIHOST.H    DPMI host class
  281.     SEGMENT.H    All memory related classes
  282.     REALPROC.H    Real procedure class
  283.     REALINT.H    Real interrupt class
  284.     CALLBACK.H    Real mode call-back class
  285.     DPMIINT.H    Interrupt handler classes
  286.     EXCEPTIO.H    Processor exception handler class
  287.  
  288.  
  289.  General note: Many of the constructors make calls to DPMI.  Since the
  290.  constructors for statically allocated class instances are called prior
  291.  to main(), declaring instances from the DPMI classes statically may
  292.  result in attempting to call DPMI prior to entering protected mode,
  293.  which probably will cause a system crash.  Therefore, DPMI objects
  294.  should be created dynamically, either as automatics (on a function's
  295.  local stack frame) or with the new operator.  It is certainly allowable
  296.  to statically allocate pointers to DPMI objects, and initialize them
  297.  after entering protected mode in order to gain global addressability.
  298.  
  299.  *--------------------------------------------------------------------
  300.  
  301.  Header File: DPMIHOST.H  See examples XMEM, XREAL, XCEPT, XINTR
  302.  
  303.  Classes    Members
  304.  -------    -------
  305.  DPMIhost
  306.         DPMIhost        Constructor; checks presence of a
  307.                     DPMI host, and gathers needed
  308.                     host information.
  309.         getStatus        Used to verify detection of DPMI host
  310.         enterProtectedMode    Makes the initial switch into
  311.                     protected mode.
  312.         getProcessor        Returns processor code
  313.         getVersion        Returns major and minor version.
  314.         getSelectorDelta    Returns delta between consecutive
  315.                     selectors.
  316.  
  317.  When you declare a DPMIhost object in your program, the constructor tests
  318.  for the presence of a DPMI host on your system.  If found, the constructor
  319.  collects information from the host needed for the switch into protected mode.
  320.  
  321.  You can determine the success or failure of the constructor by calling the
  322.  getStatus member, which returns DPMIok if the constructor found a DPMI host
  323.  and was successfully initialized.  The members getProcessor, getVersion,
  324.  and getSelectorDelta simply return the appropriate host parameters.
  325.  
  326.  You use the member enterProtectedMode for the initial switch into protected
  327.  mode, and after that it should not be called.    It first allocates a block
  328.  of DOS memory to satisfy the host's private data area requirements.  It then
  329.  calls the mode switch entry point obtained by the constructor.  When this
  330.  returns, the processor is running in protected mode.  Finally, this member
  331.  relocates the executable image for protected mode operation (see
  332.  Implementation Notes for details).  The enterProtectedMode member returns
  333.  TRUE if the processor is successfully switched to protected mode.
  334.  *--------------------------------------------------------------------
  335.  
  336.  Header File: SEGMENT.H  See example XMEM
  337.  
  338.  Classes    Members
  339.  -------    -------
  340.  Block
  341.         Block            Constructor; allocates raw block
  342.                     of memory from DPMI.
  343.         ~Block            Destructor; release block to DPMI
  344.         setSize         Resize function reallocates block.
  345.         blockHandle        Returns block handle.
  346.         blockSize        Returns block size.
  347.         blockBase        Returns base linear address.
  348.  
  349.  AbstractSegment
  350.         segmentSize        Returns size of segment.
  351.         segmentBase        Returns base of segment.
  352.         resize            Resizes segment.
  353.         move            Changes segment base.
  354.         operator+        Adds a segment property.
  355.         operator-        Removes a segment property.
  356.         queryProp        Tests for segment property.
  357.  Segment
  358.  : AbstractSegment
  359.         Segment(void)        Generic constructor.
  360.         Segment(selector_t)    Specific descriptor.
  361.         Segment(AbstractSegment&) Alias to existing segment.
  362.         ~Segment(void);     Releases descriptor to DPMI.
  363.  
  364.  
  365.  CommonRealSegment
  366.  : AbstractSegment
  367.         CommonRealSegment    Constructor
  368.  
  369.  DOSMemory
  370.  : AbstractSegment
  371.         DOSMemory        Constructor
  372.         ~DOSMemory        Destructor
  373.  
  374.  
  375.  HugeSegment
  376.  : AbstractSegment
  377.         HugeSegment        Constructor
  378.         ~HugeSegment        Destructor
  379.  
  380.  MemorySegment
  381.  : AbstractSegment, Block
  382.         MemorySegment(uShort)    Constructor
  383.         MemorySegment(uShort,    Constructor for specific descriptor
  384.             selector_t)
  385.         ~MemorySegment        Destructor-frees block and descriptor
  386.  
  387.  
  388.  
  389.  HugeMemorySegment
  390.  : HugeSegment, Block
  391.  
  392.  
  393.  The various memory classes provide structured access to DPMI's memory
  394.  management facilities.
  395.  
  396.  Note that of the classes defined, DOSMemory, MemorySegment, and
  397.  HugeMemorySegment are unique in they that combine allocated memory and
  398.  descriptors to address that memory.  The other classes are either
  399.  just memory (e.g. Block) or just descriptors (e.g. Segment, HugeSegment).
  400.  The distinctions between memory and descriptors are important to
  401.  the conceptualization of the memory classes.
  402.  
  403.  *......................................................................
  404.  
  405.  The Block class corresponds to raw memory blocks allocated via DPMI
  406.  function 501h.  Defined operations on Blocks are limited to resize,
  407.  and free.  The class also supports query of the DPMI memory handle and
  408.  query of the block size. Blocks by themselves are not especially useful,
  409.  since the memory is not addressable.  Its purpose is to serve as a
  410.  base class for MemorySegment and HugeMemorySegment.
  411.  
  412.  *......................................................................
  413.  
  414.  AbstractSegment is an abstract class the corresponds to a descriptor.
  415.  DPMI provides several means to create descriptors, all with slightly
  416.  different behavior. Although most members of AbstractSegment are pure,
  417.  a key member that it does implement is ptrTo, which returns a far
  418.  pointer that may be used to reference the linear address space that
  419.  the corresponding descriptor points to.
  420.  
  421.  *......................................................................
  422.  
  423.  The SegmentProperty enumeration provides an elegant means to add,
  424.  remove, and query properties of instances of derived classes of the
  425.  AbstractSegment class. It is defined as:
  426.  
  427.     typedef enum SegmentProperty
  428.     {
  429.         present,
  430.         executable,
  431.         readable,
  432.         writable,
  433.         big,
  434.         expandDown
  435.     } SegmentProp_t;
  436.  
  437.  The AbstractSegment class defines members operator+(SegmentProp_t) and
  438.  operator-(SegmentProp_t) that allow properties to be added and removed
  439.  with a natural syntax. For example, the code
  440.  
  441.     Segment mySeg();
  442.     mySeg - present;
  443.  
  444.  creates a descriptor and makes it not present.
  445.  
  446.  *......................................................................
  447.  
  448.  The Segment class corresponds to generic, fully modifiable LDT descriptors.
  449.  There are three DPMI services that create such descriptors, and thus
  450.  three constructors for the class. The first corresponds to DPMI function
  451.  0000, which allocates a descriptor.  The second corresponds to DPMI
  452.  function 000Dh, which allocates a specific descriptor.  The last
  453.  constructor corresponds to DPMI function 000Ah, which creates an alias
  454.  (same base and limit) to an existing segment.
  455.  
  456.  The default properties are present and writable. New Segments have a
  457.  base of zero and a size of one.
  458.  
  459.  The argument for the resize method is in bytes, and size==0
  460.  specifies a size of 64 KB.
  461.  
  462.  Specific descriptors must be in the range 04h to 0FFh.
  463.  
  464.  *......................................................................
  465.  
  466.  The CommonRealSegment class corresponds to descriptors created by DPMI
  467.  function 0002h, Convert Paragraph to Selector.  The intended use of
  468.  this function is to provide addressability from protected mode for
  469.  commonly accessed regions of the low megabyte, such as the BIOS data
  470.  area (paragraph 40h) or the video display area (B800h etc.).
  471.  
  472.  DPMI restricts modification of descriptors created by function 0002h, and
  473.  therefore the resize, move, operator+(SegmentProp_t) and
  474.  operator-(SegmentProp_t) members all return FALSE. Other members are
  475.  inherited from AbstractSegment.
  476.  
  477.  *......................................................................
  478.  
  479.  The DOSMemory class corresponds to DPMI function 100h.  The constructor
  480.  uses this function to allocate a block of memory from DOS.  DPMI provides
  481.  a descriptor that allows addressability of the block from protected mode.
  482.  The argument to the constructor is the desired size in paragraphs of the
  483.  block.  If the allocation fails, the ptrTo function returns zero. The
  484.  paragraph address of the block is available via the segmentBase(void)
  485.  member inherited from AbstractSegment.
  486.  
  487.  This code fragment:
  488.  
  489.     DOSMemory d(0x100);
  490.  
  491.     char far *p = (char far *)d.ptrTo();
  492.  
  493.  allocates 0x100 paragraphs of DOS memory and initializes a pointer to
  494.  it.  If the allocation fails, p is a null pointer.
  495.  
  496.  The resize member for DOSMemory maps to DPMI function 102h, Resize DOS
  497.  Memory Block; similarly, the destructor maps to function 101h, Free
  498.  DOS Memory Block. Because DPMI restricts any other modifications to these
  499.  blocks, the operator+(SegmentProp_t), operator-(SegmentProp_t), and move
  500.  members all return FALSE;
  501.  
  502.  *......................................................................
  503.  
  504.  A HugeSegment corresponds to a set of consecutive descriptors, which are
  505.  set up to span a address region of arbitrary size. The difference between
  506.  the base addresses of consecutive descriptors is 64 KB. The argument to
  507.  the constructor is the size in bytes of the segment.
  508.  
  509.  For example, the code fragment
  510.  
  511.     HugeSegment  h(0x28000);
  512.     h.move(0x500000);
  513.  
  514.  results in the allocation of three descriptors having sizes of 0x10000,
  515.  0x10000, and 0x8000.  Calling the move member sets the base addresses
  516.  of the three descriptors to 0x500000, 0x510000, and 0x520000.
  517.  
  518.  Operations on a HugeSegment, such as adding or removing a property,
  519.  affect all of its component descriptors.  Likewise, the destructor
  520.  frees all the descriptors.
  521.  
  522.  HugeSegments cannot be grown if the new desired size requires additional
  523.  descriptors to span the region.  Shrinking a HugeSegment frees descriptors
  524.  no longer required to span it, and these cannot be reallocated to
  525.  return the segment to its original size.
  526.  
  527.  *......................................................................
  528.  
  529.  A MemorySegment is a generic descriptor mapped to a block of DPMI memory.
  530.  The size is restricted by the argument to the constructor to be 64 KB
  531.  or less.  Declaring a MemorySegment results in allocating both memory
  532.  and a descriptor initialized to address that memory.
  533.  
  534.  The code fragment
  535.  
  536.         MemorySegment m(0x500);
  537.         short far *p = (short far *)m.ptrTo();
  538.  
  539.  makes p a far pointer to a 0x500 byte block of memory.  An zero argument
  540.  to the constructor requests a 64 KB block.
  541.  
  542.  An alternate constructor allows the MemorySegment to be allocated with
  543.  a specific descriptor.
  544.  
  545.  The resize and property members work as expected, but the move member
  546.  returns FALSE since DPMI provides no means to move memory blocks.
  547.  
  548.  
  549.  *......................................................................
  550.  
  551.  A HugeMemorySegment is to a MemorySegment as a HugeSegment is to a
  552.  Segment.  A HugeMemorySegment is an arbitrarily large block of memory
  553.  with a set of consecutive descriptors that are set up to span it.  The
  554.  argument to the constructor is the size in bytes. As for MemorySegment,
  555.  the move member returns FALSE.
  556.  
  557.  
  558.  HugeMemorySegments cannot be grown if the new desired size requires
  559.  additional descriptors to span the region.  Shrinking a HugeMemorySegment
  560.  frees descriptors no longer required to span it, and these cannot be
  561.  reallocated to return the segment to its original size.
  562.  
  563.  *--------------------------------------------------------------------
  564.  
  565.  Header File: REALPROC.H  See example XREAL
  566.  
  567.  Classes    Members
  568.  -------    -------
  569.  RealProcedure
  570.         RealProcedure        Constructor.
  571.         operator()        Call operator invokes real
  572.                     mode procedure.
  573.         operator char()     char cast extracts char return
  574.                     value from real mode call structure.
  575.         operator int()        int cast extracts int return
  576.                     value from real mode call structure.
  577.         operator long()     long cast extracts long return
  578.                     value from real mode call structure.
  579.  
  580.  Applications occasionally require certain routines that cannot run in
  581.  real mode, and must switch to real mode to execute them.  The RealProcedure
  582.  class corresponds to DPMI mechanisms for invoking (far) functions in
  583.  real mode.
  584.  
  585.  The arguments for the constructor are the address of the real procedure
  586.  and the number of bytes of arguments the real procedure expects on the
  587.  stack when it is invoked.  The second argument is optional and defaults
  588.  to zero.  The procedure address is near, and is assumed to be in the
  589.  default code segment.
  590.  
  591.  To invoke the RealProcedure, simply call it.  The class overrides the
  592.  call operator, and the member operator() makes the necessary DPMI calls
  593.  to run the registered routine in real mode.  The stack arguments, if any,
  594.  are copied to the stack on which the real mode routine is invoked.
  595.  
  596.  The class ensures that DS==SS when the real mode routine executes. Thus
  597.  the real mode routine can use any near pointers.
  598.  
  599.  An additional feature of the RealProcedure class is the ability to
  600.  return values.  Each class instance contains a dpmiRegs_t structure that
  601.  is used to pass the register state between modes. Upon return to protected
  602.  mode, this structure holds the register state in effect when the real
  603.  routine returned, and return values are contained therein.  To access
  604.  them, use the cast override members: operator char(), operator int() and
  605.  operator long().  Refer to the example code to see exactly how this is done.
  606.  *--------------------------------------------------------------------
  607.  
  608.  Header File: REALINT.H   See example XREAL
  609.  
  610.  Classes    Members
  611.  -------    -------
  612.  RealInterrupt
  613.         RealInterrupt        Constructor
  614.         operator()        Call operator invokes interrupt
  615.                     handler in real mode.
  616.  
  617.  A RealInterrupt corresponds to the DPMI function that switches to
  618.  real mode and issues a particular interrupt after installing a
  619.  register state supplied by the caller.  Unlike the RealProcedure class,
  620.  the interface to RealInterrupt assumes register-based argument passing.
  621.  
  622.  The argument to the constructor is the number of the interrupt, from
  623.  zero to 255.  The member operator() (call override operator) is used
  624.  to invoke the real mode interrupt.  This requires a dpmiRegs_t
  625.  structure as an argument.  Upon return from the interrupt, the dpmiRegs_t
  626.  structure reflects the register state at the time the real mode
  627.  interrupt handler returned.
  628.  
  629.  The caller is required to set up the dpmiRegs_t structure that is passed
  630.  when the real interrupt is called.  This includes setting up the stack
  631.  (SS:SP fields) and the flags.    Setting SS and SP requests the DPMI host
  632.  to provide a stack.  The flags value should be chosen carefully,
  633.  especially with regard to the Interrupt Enable bit and the Trace bit.
  634.  
  635.  An example of using a RealInterrupt is included in the TestCallBack function
  636.  of the XREAL.CPP example.
  637.  
  638.  *--------------------------------------------------------------------
  639.  
  640.  
  641.  Header File: CALLBACK.H  See example XREAL
  642.  
  643.  Classes    Members
  644.  -------    -------
  645.  CallBack    CallBack        Constructor; allocates real mode
  646.                     call-back and initialize register
  647.                     structure; saves callback address
  648.         ~CallBack        Destructor; releases call back.
  649.         getCallBackAddress    Returns the call back address.
  650.  
  651.  DPMI provides a mechanism for call protected mode routines from real
  652.  mode.    Unfortunately, the mechanism is rather complex.  The CallBack
  653.  class goes a long way in simplifying the task of using real mode
  654.  call backs.
  655.  
  656.  The single arguemnt to the constructor is the address of the call back
  657.  handler.  The call back handler is a routine that called from real mode
  658.  but runs in protected mode.  The class includes dispatching logic that
  659.  allows you to code the handler as a normal near routine, and allows you to
  660.  assume that DS==SS.  The argument to the handler is a dpmiRegs_t
  661.  structure that reflects the interrupt state at the time of the call.
  662.  Any changes the handler makes to this structure are reflected in the
  663.  register state when the handler returns to real mode.
  664.  
  665.  
  666.  The handler should only be invoked by calling to the far callback address
  667.  from real mode.  The callback address is obtained with the getCallBackAddress
  668.  member.  See function TestCallBack in the XREAL example.
  669.  
  670.  *......................................................................
  671.  
  672.  Header File: DPMIINT.H  See examples XINTR, XREAL
  673.  
  674.  Classes    Members
  675.  -------    -------
  676.  InterruptHandler
  677.         InterruptHandler    Constructor; hooks interrupt.
  678.         ~InterruptHandler    Destructor; unhooks interrupt.
  679.         callPrevious        Invokes previous handler.
  680.  
  681.  RealInterruptHandler
  682.  : InterruptHandler
  683.         RealInterruptHandler    Constructor; hooks real interrupt.
  684.         ~RealInterruptHandler    Destructor; unhooks real interrupt.
  685.  
  686.  
  687.  The interrupt handling classes make it very easy to create handlers for
  688.  hardware and software interrupts, both in real mode and protected mode.
  689.  The class handles all the necessary interaction with DPMI for saving the
  690.  previous vector, and for setting the interrupt vector to the user's handler.
  691.  
  692.  The class further simplifies creation of handlers by allowing the user
  693.  to code the handler as a normal function, i.e, the user does not need to
  694.  declare it as _interrupt, and may assume that DS==SS, which is important
  695.  in small model programs.  This is accomplished by the interrupt dispatching
  696.  logic built into the class (see Implementation Notes for more information).
  697.  
  698.  The arguments to the constructor are the interrupt number and the address
  699.  of the routine that the user assigns to handle the interrupt. The argument
  700.  to the user's handler routine is a dpmiRegs_t structure, which reflects
  701.  the register state at the time the interrupt occurs.  Changes to the
  702.  dpmiRegs_t argument made by the handler are reflected as changes to the
  703.  register state when the handler returns.  For example, a software interrupt
  704.  handler that returns a value in AX modifies the drAX field of the dpmiRegs_t
  705.  argument. Likewise, a hardware interrupt handler which preserves the
  706.  register state must make no changes to the dpmiRegs_t argument.
  707.  
  708.  The member callPrevious is useful for calling the handler that was in
  709.  effect when the user handler was created.  The argument to callPrevious
  710.  is a pointer to the dpmiRegs_t structure, which is necessary in order
  711.  to present the correct register state to the previous handler.  Any changes
  712.  made to the register state by the previous handler are reflected in the
  713.  dpmiRegs_t structure upon return. RealInterruptHandlers inherit this member.
  714.  
  715.  The destructors restore the previous vector.
  716.  
  717.  *--------------------------------------------------------------------
  718.  
  719.  Header file: EXCEPTIO.H  See example XCEPT
  720.  
  721.  Classes    Members
  722.  -------    -------
  723.  ExceptionHandler
  724.         ExceptionHandler    Constructor. Hooks exception.
  725.         ~ExceptionHandler    Destructor. Restores vector
  726.         callPrevious        Invokes previous handler.
  727.  
  728.  The ExceptionHandler class makes it easy to create handlers for
  729.  processor exceptions, such as General Protection violation, Segment
  730.  Not Present, etc.  As with InterruptHandlers, the class provides
  731.  dispatching such that handlers run with DS==SS, so that all near pointers
  732.  are valid, and handlers are declared as normal near functions.
  733.  
  734.  The arguments to the constructor are the exception number to handle,
  735.  and the address of the handler.  The class takes care of calling DPMI
  736.  to get the previous vector and set up for the new handler.
  737.  
  738.  When the handler is invoked, there are two structures passed to it. The
  739.  first is a dpmiRegs_t structure which reflects the register state at
  740.  the time the exception occurred.  The second is the DPMI exception
  741.  frame, which gives the CS:IP, SS:SP, and flags at the time of the
  742.  exception.  The handler may modify fields in the register structure
  743.  and/or the exception frame structure, and such changes are observed
  744.  by the host when the handler returns.
  745.  
  746.  The member callPrevious is used to invoke the previous handler for the
  747.  exception.  It is passed pointers to the register state and to the
  748.  exception frame, which it may modify.
  749.